{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.11.0\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/antonio/anaconda3/envs/geometric_new/lib/python3.9/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import torch\n",
    "os.environ['TORCH'] = torch.__version__\n",
    "print(torch.__version__)\n",
    "\n",
    "!pip install -q torch-scatter -f https://data.pyg.org/whl/torch-${TORCH}.html\n",
    "!pip install -q torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.html\n",
    "!pip install -q git+https://github.com/pyg-team/pytorch_geometric.git"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch_geometric.datasets import Planetoid\n",
    "import torch_geometric.transforms as T\n",
    "from torch_geometric.nn import GCNConv\n",
    "from torch_geometric.utils import train_test_split_edges"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial 6  \n",
    "Graph AutoEncoders GAE &  \n",
    "Variational Graph Autoencoders VGAE    \n",
    "\n",
    "[paper](https://arxiv.org/pdf/1611.07308.pdf)  \n",
    "[code](https://github.com/rusty1s/pytorch_geometric/blob/master/examples/autoencoder.py)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Graph AutoEncoder GAE"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.x\n",
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.tx\n",
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.allx\n",
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.y\n",
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.ty\n",
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.ally\n",
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.graph\n",
      "Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.citeseer.test.index\n",
      "Processing...\n",
      "Done!\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Data(x=[3327, 3703], edge_index=[2, 9104], y=[3327], train_mask=[3327], val_mask=[3327], test_mask=[3327])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset = Planetoid(\"\\..\", \"CiteSeer\", transform=T.NormalizeFeatures())\n",
    "dataset.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Data(x=[3327, 3703], edge_index=[2, 9104], y=[3327])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = dataset[0]\n",
    "data.train_mask = data.val_mask = data.test_mask = None\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/antonio/anaconda3/envs/geometric_new/lib/python3.9/site-packages/torch_geometric/deprecation.py:12: UserWarning: 'train_test_split_edges' is deprecated, use 'transforms.RandomLinkSplit' instead\n",
      "  warnings.warn(out)\n"
     ]
    }
   ],
   "source": [
    "data = train_test_split_edges(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Data(x=[3327, 3703], y=[3327], val_pos_edge_index=[2, 227], test_pos_edge_index=[2, 455], train_pos_edge_index=[2, 7740], train_neg_adj_mask=[3327, 3327], val_neg_edge_index=[2, 227], test_neg_edge_index=[2, 455])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the Encoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class GCNEncoder(torch.nn.Module):\n",
    "    def __init__(self, in_channels, out_channels):\n",
    "        super(GCNEncoder, self).__init__()\n",
    "        self.conv1 = GCNConv(in_channels, 2 * out_channels, cached=True) # cached only for transductive learning\n",
    "        self.conv2 = GCNConv(2 * out_channels, out_channels, cached=True) # cached only for transductive learning\n",
    "\n",
    "    def forward(self, x, edge_index):\n",
    "        x = self.conv1(x, edge_index).relu()\n",
    "        return self.conv2(x, edge_index)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the Autoencoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch_geometric.nn import GAE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# parameters\n",
    "out_channels = 2\n",
    "num_features = dataset.num_features\n",
    "epochs = 100\n",
    "\n",
    "# model\n",
    "model = GAE(GCNEncoder(num_features, out_channels))\n",
    "\n",
    "# move to GPU (if available)\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "model = model.to(device)\n",
    "x = data.x.to(device)\n",
    "train_pos_edge_index = data.train_pos_edge_index.to(device)\n",
    "\n",
    "# inizialize the optimizer\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.01)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train():\n",
    "    model.train()\n",
    "    optimizer.zero_grad()\n",
    "    z = model.encode(x, train_pos_edge_index)\n",
    "    loss = model.recon_loss(z, train_pos_edge_index)\n",
    "    #if args.variational:\n",
    "    #   loss = loss + (1 / data.num_nodes) * model.kl_loss()\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "    return float(loss)\n",
    "\n",
    "\n",
    "def test(pos_edge_index, neg_edge_index):\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        z = model.encode(x, train_pos_edge_index)\n",
    "    return model.test(z, pos_edge_index, neg_edge_index)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 001, AUC: 0.6280, AP: 0.6691\n",
      "Epoch: 002, AUC: 0.6498, AP: 0.6876\n",
      "Epoch: 003, AUC: 0.6555, AP: 0.6970\n",
      "Epoch: 004, AUC: 0.6585, AP: 0.6971\n",
      "Epoch: 005, AUC: 0.6600, AP: 0.6978\n",
      "Epoch: 006, AUC: 0.6608, AP: 0.7002\n",
      "Epoch: 007, AUC: 0.6614, AP: 0.7029\n",
      "Epoch: 008, AUC: 0.6616, AP: 0.7038\n",
      "Epoch: 009, AUC: 0.6620, AP: 0.7039\n",
      "Epoch: 010, AUC: 0.6624, AP: 0.7045\n",
      "Epoch: 011, AUC: 0.6624, AP: 0.7055\n",
      "Epoch: 012, AUC: 0.6624, AP: 0.7065\n",
      "Epoch: 013, AUC: 0.6626, AP: 0.7078\n",
      "Epoch: 014, AUC: 0.6627, AP: 0.7090\n",
      "Epoch: 015, AUC: 0.6627, AP: 0.7105\n",
      "Epoch: 016, AUC: 0.6617, AP: 0.7115\n",
      "Epoch: 017, AUC: 0.6613, AP: 0.7135\n",
      "Epoch: 018, AUC: 0.6601, AP: 0.7145\n",
      "Epoch: 019, AUC: 0.6589, AP: 0.7155\n",
      "Epoch: 020, AUC: 0.6571, AP: 0.7160\n",
      "Epoch: 021, AUC: 0.6562, AP: 0.7170\n",
      "Epoch: 022, AUC: 0.6558, AP: 0.7180\n",
      "Epoch: 023, AUC: 0.6561, AP: 0.7193\n",
      "Epoch: 024, AUC: 0.6559, AP: 0.7196\n",
      "Epoch: 025, AUC: 0.6562, AP: 0.7204\n",
      "Epoch: 026, AUC: 0.6569, AP: 0.7211\n",
      "Epoch: 027, AUC: 0.6574, AP: 0.7218\n",
      "Epoch: 028, AUC: 0.6585, AP: 0.7227\n",
      "Epoch: 029, AUC: 0.6596, AP: 0.7233\n",
      "Epoch: 030, AUC: 0.6615, AP: 0.7246\n",
      "Epoch: 031, AUC: 0.6646, AP: 0.7264\n",
      "Epoch: 032, AUC: 0.6684, AP: 0.7282\n",
      "Epoch: 033, AUC: 0.6734, AP: 0.7302\n",
      "Epoch: 034, AUC: 0.6791, AP: 0.7327\n",
      "Epoch: 035, AUC: 0.6846, AP: 0.7349\n",
      "Epoch: 036, AUC: 0.6900, AP: 0.7370\n",
      "Epoch: 037, AUC: 0.6963, AP: 0.7396\n",
      "Epoch: 038, AUC: 0.7023, AP: 0.7423\n",
      "Epoch: 039, AUC: 0.7096, AP: 0.7454\n",
      "Epoch: 040, AUC: 0.7182, AP: 0.7493\n",
      "Epoch: 041, AUC: 0.7271, AP: 0.7538\n",
      "Epoch: 042, AUC: 0.7352, AP: 0.7579\n",
      "Epoch: 043, AUC: 0.7411, AP: 0.7613\n",
      "Epoch: 044, AUC: 0.7457, AP: 0.7640\n",
      "Epoch: 045, AUC: 0.7503, AP: 0.7665\n",
      "Epoch: 046, AUC: 0.7545, AP: 0.7687\n",
      "Epoch: 047, AUC: 0.7576, AP: 0.7704\n",
      "Epoch: 048, AUC: 0.7602, AP: 0.7717\n",
      "Epoch: 049, AUC: 0.7624, AP: 0.7729\n",
      "Epoch: 050, AUC: 0.7658, AP: 0.7748\n",
      "Epoch: 051, AUC: 0.7681, AP: 0.7759\n",
      "Epoch: 052, AUC: 0.7704, AP: 0.7769\n",
      "Epoch: 053, AUC: 0.7714, AP: 0.7773\n",
      "Epoch: 054, AUC: 0.7726, AP: 0.7780\n",
      "Epoch: 055, AUC: 0.7733, AP: 0.7783\n",
      "Epoch: 056, AUC: 0.7740, AP: 0.7784\n",
      "Epoch: 057, AUC: 0.7748, AP: 0.7788\n",
      "Epoch: 058, AUC: 0.7754, AP: 0.7792\n",
      "Epoch: 059, AUC: 0.7759, AP: 0.7799\n",
      "Epoch: 060, AUC: 0.7760, AP: 0.7803\n",
      "Epoch: 061, AUC: 0.7768, AP: 0.7809\n",
      "Epoch: 062, AUC: 0.7772, AP: 0.7807\n",
      "Epoch: 063, AUC: 0.7774, AP: 0.7808\n",
      "Epoch: 064, AUC: 0.7775, AP: 0.7811\n",
      "Epoch: 065, AUC: 0.7779, AP: 0.7814\n",
      "Epoch: 066, AUC: 0.7781, AP: 0.7817\n",
      "Epoch: 067, AUC: 0.7784, AP: 0.7819\n",
      "Epoch: 068, AUC: 0.7788, AP: 0.7819\n",
      "Epoch: 069, AUC: 0.7792, AP: 0.7821\n",
      "Epoch: 070, AUC: 0.7798, AP: 0.7826\n",
      "Epoch: 071, AUC: 0.7802, AP: 0.7831\n",
      "Epoch: 072, AUC: 0.7804, AP: 0.7833\n",
      "Epoch: 073, AUC: 0.7809, AP: 0.7836\n",
      "Epoch: 074, AUC: 0.7811, AP: 0.7837\n",
      "Epoch: 075, AUC: 0.7813, AP: 0.7842\n",
      "Epoch: 076, AUC: 0.7820, AP: 0.7851\n",
      "Epoch: 077, AUC: 0.7822, AP: 0.7857\n",
      "Epoch: 078, AUC: 0.7825, AP: 0.7860\n",
      "Epoch: 079, AUC: 0.7827, AP: 0.7863\n",
      "Epoch: 080, AUC: 0.7833, AP: 0.7868\n",
      "Epoch: 081, AUC: 0.7838, AP: 0.7876\n",
      "Epoch: 082, AUC: 0.7841, AP: 0.7879\n",
      "Epoch: 083, AUC: 0.7840, AP: 0.7878\n",
      "Epoch: 084, AUC: 0.7842, AP: 0.7880\n",
      "Epoch: 085, AUC: 0.7845, AP: 0.7884\n",
      "Epoch: 086, AUC: 0.7845, AP: 0.7885\n",
      "Epoch: 087, AUC: 0.7843, AP: 0.7885\n",
      "Epoch: 088, AUC: 0.7840, AP: 0.7883\n",
      "Epoch: 089, AUC: 0.7836, AP: 0.7878\n",
      "Epoch: 090, AUC: 0.7836, AP: 0.7880\n",
      "Epoch: 091, AUC: 0.7838, AP: 0.7883\n",
      "Epoch: 092, AUC: 0.7836, AP: 0.7883\n",
      "Epoch: 093, AUC: 0.7832, AP: 0.7880\n",
      "Epoch: 094, AUC: 0.7830, AP: 0.7879\n",
      "Epoch: 095, AUC: 0.7829, AP: 0.7880\n",
      "Epoch: 096, AUC: 0.7826, AP: 0.7878\n",
      "Epoch: 097, AUC: 0.7824, AP: 0.7878\n",
      "Epoch: 098, AUC: 0.7821, AP: 0.7880\n",
      "Epoch: 099, AUC: 0.7819, AP: 0.7879\n",
      "Epoch: 100, AUC: 0.7817, AP: 0.7879\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(1, epochs + 1):\n",
    "    loss = train()\n",
    "\n",
    "    auc, ap = test(data.test_pos_edge_index, data.test_neg_edge_index)\n",
    "    print('Epoch: {:03d}, AUC: {:.4f}, AP: {:.4f}'.format(epoch, auc, ap))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[-0.3415,  0.3505],\n",
       "        [ 0.8631, -1.1042],\n",
       "        [-0.7020,  0.8189],\n",
       "        ...,\n",
       "        [ 0.0874, -0.0409],\n",
       "        [-0.6144,  0.7314],\n",
       "        [-0.6832,  0.7997]], device='cuda:0', grad_fn=<AddBackward0>)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = model.encode(x, train_pos_edge_index)\n",
    "Z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Are the results (AUC) and (AP) easy to read and compare?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Use Tensorboard"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# parameters\n",
    "out_channels = 2\n",
    "num_features = dataset.num_features\n",
    "epochs = 100\n",
    "\n",
    "# model\n",
    "model = GAE(GCNEncoder(num_features, out_channels))\n",
    "\n",
    "# move to GPU (if available)\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "model = model.to(device)\n",
    "x = data.x.to(device)\n",
    "train_pos_edge_index = data.train_pos_edge_index.to(device)\n",
    "\n",
    "# inizialize the optimizer\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.01)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import tensorboard\n",
    "\n",
    "#### Installation: (if needed) \"pip install tensorboard\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "writer = SummaryWriter('runs/GAE1_experiment_'+'2d_100_epochs')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 001, AUC: 0.6298, AP: 0.6217\n",
      "Epoch: 002, AUC: 0.6272, AP: 0.6813\n",
      "Epoch: 003, AUC: 0.6465, AP: 0.6944\n",
      "Epoch: 004, AUC: 0.6518, AP: 0.6967\n",
      "Epoch: 005, AUC: 0.6514, AP: 0.7032\n",
      "Epoch: 006, AUC: 0.6478, AP: 0.7085\n",
      "Epoch: 007, AUC: 0.6490, AP: 0.7121\n",
      "Epoch: 008, AUC: 0.6537, AP: 0.7146\n",
      "Epoch: 009, AUC: 0.6570, AP: 0.7146\n",
      "Epoch: 010, AUC: 0.6574, AP: 0.7163\n",
      "Epoch: 011, AUC: 0.6569, AP: 0.7187\n",
      "Epoch: 012, AUC: 0.6565, AP: 0.7201\n",
      "Epoch: 013, AUC: 0.6569, AP: 0.7207\n",
      "Epoch: 014, AUC: 0.6574, AP: 0.7213\n",
      "Epoch: 015, AUC: 0.6575, AP: 0.7222\n",
      "Epoch: 016, AUC: 0.6571, AP: 0.7228\n",
      "Epoch: 017, AUC: 0.6570, AP: 0.7236\n",
      "Epoch: 018, AUC: 0.6569, AP: 0.7242\n",
      "Epoch: 019, AUC: 0.6572, AP: 0.7245\n",
      "Epoch: 020, AUC: 0.6572, AP: 0.7251\n",
      "Epoch: 021, AUC: 0.6574, AP: 0.7253\n",
      "Epoch: 022, AUC: 0.6585, AP: 0.7261\n",
      "Epoch: 023, AUC: 0.6599, AP: 0.7268\n",
      "Epoch: 024, AUC: 0.6618, AP: 0.7278\n",
      "Epoch: 025, AUC: 0.6636, AP: 0.7284\n",
      "Epoch: 026, AUC: 0.6667, AP: 0.7300\n",
      "Epoch: 027, AUC: 0.6710, AP: 0.7316\n",
      "Epoch: 028, AUC: 0.6754, AP: 0.7330\n",
      "Epoch: 029, AUC: 0.6812, AP: 0.7351\n",
      "Epoch: 030, AUC: 0.6867, AP: 0.7369\n",
      "Epoch: 031, AUC: 0.6920, AP: 0.7390\n",
      "Epoch: 032, AUC: 0.6981, AP: 0.7414\n",
      "Epoch: 033, AUC: 0.7043, AP: 0.7441\n",
      "Epoch: 034, AUC: 0.7113, AP: 0.7472\n",
      "Epoch: 035, AUC: 0.7179, AP: 0.7502\n",
      "Epoch: 036, AUC: 0.7241, AP: 0.7532\n",
      "Epoch: 037, AUC: 0.7300, AP: 0.7562\n",
      "Epoch: 038, AUC: 0.7362, AP: 0.7595\n",
      "Epoch: 039, AUC: 0.7426, AP: 0.7629\n",
      "Epoch: 040, AUC: 0.7473, AP: 0.7656\n",
      "Epoch: 041, AUC: 0.7498, AP: 0.7671\n",
      "Epoch: 042, AUC: 0.7523, AP: 0.7687\n",
      "Epoch: 043, AUC: 0.7560, AP: 0.7708\n",
      "Epoch: 044, AUC: 0.7603, AP: 0.7733\n",
      "Epoch: 045, AUC: 0.7620, AP: 0.7745\n",
      "Epoch: 046, AUC: 0.7633, AP: 0.7756\n",
      "Epoch: 047, AUC: 0.7647, AP: 0.7765\n",
      "Epoch: 048, AUC: 0.7667, AP: 0.7776\n",
      "Epoch: 049, AUC: 0.7674, AP: 0.7776\n",
      "Epoch: 050, AUC: 0.7677, AP: 0.7777\n",
      "Epoch: 051, AUC: 0.7682, AP: 0.7781\n",
      "Epoch: 052, AUC: 0.7693, AP: 0.7782\n",
      "Epoch: 053, AUC: 0.7704, AP: 0.7783\n",
      "Epoch: 054, AUC: 0.7712, AP: 0.7782\n",
      "Epoch: 055, AUC: 0.7712, AP: 0.7786\n",
      "Epoch: 056, AUC: 0.7716, AP: 0.7789\n",
      "Epoch: 057, AUC: 0.7724, AP: 0.7787\n",
      "Epoch: 058, AUC: 0.7725, AP: 0.7780\n",
      "Epoch: 059, AUC: 0.7728, AP: 0.7781\n",
      "Epoch: 060, AUC: 0.7734, AP: 0.7788\n",
      "Epoch: 061, AUC: 0.7739, AP: 0.7791\n",
      "Epoch: 062, AUC: 0.7742, AP: 0.7795\n",
      "Epoch: 063, AUC: 0.7747, AP: 0.7803\n",
      "Epoch: 064, AUC: 0.7751, AP: 0.7799\n",
      "Epoch: 065, AUC: 0.7754, AP: 0.7800\n",
      "Epoch: 066, AUC: 0.7758, AP: 0.7805\n",
      "Epoch: 067, AUC: 0.7759, AP: 0.7809\n",
      "Epoch: 068, AUC: 0.7760, AP: 0.7811\n",
      "Epoch: 069, AUC: 0.7764, AP: 0.7810\n",
      "Epoch: 070, AUC: 0.7764, AP: 0.7808\n",
      "Epoch: 071, AUC: 0.7768, AP: 0.7813\n",
      "Epoch: 072, AUC: 0.7773, AP: 0.7825\n",
      "Epoch: 073, AUC: 0.7778, AP: 0.7829\n",
      "Epoch: 074, AUC: 0.7780, AP: 0.7829\n",
      "Epoch: 075, AUC: 0.7780, AP: 0.7825\n",
      "Epoch: 076, AUC: 0.7778, AP: 0.7815\n",
      "Epoch: 077, AUC: 0.7778, AP: 0.7815\n",
      "Epoch: 078, AUC: 0.7785, AP: 0.7825\n",
      "Epoch: 079, AUC: 0.7789, AP: 0.7831\n",
      "Epoch: 080, AUC: 0.7790, AP: 0.7831\n",
      "Epoch: 081, AUC: 0.7793, AP: 0.7831\n",
      "Epoch: 082, AUC: 0.7793, AP: 0.7830\n",
      "Epoch: 083, AUC: 0.7790, AP: 0.7825\n",
      "Epoch: 084, AUC: 0.7792, AP: 0.7827\n",
      "Epoch: 085, AUC: 0.7797, AP: 0.7831\n",
      "Epoch: 086, AUC: 0.7805, AP: 0.7839\n",
      "Epoch: 087, AUC: 0.7807, AP: 0.7840\n",
      "Epoch: 088, AUC: 0.7806, AP: 0.7838\n",
      "Epoch: 089, AUC: 0.7803, AP: 0.7836\n",
      "Epoch: 090, AUC: 0.7805, AP: 0.7837\n",
      "Epoch: 091, AUC: 0.7810, AP: 0.7843\n",
      "Epoch: 092, AUC: 0.7817, AP: 0.7851\n",
      "Epoch: 093, AUC: 0.7824, AP: 0.7854\n",
      "Epoch: 094, AUC: 0.7824, AP: 0.7855\n",
      "Epoch: 095, AUC: 0.7827, AP: 0.7863\n",
      "Epoch: 096, AUC: 0.7823, AP: 0.7860\n",
      "Epoch: 097, AUC: 0.7824, AP: 0.7861\n",
      "Epoch: 098, AUC: 0.7831, AP: 0.7866\n",
      "Epoch: 099, AUC: 0.7837, AP: 0.7868\n",
      "Epoch: 100, AUC: 0.7841, AP: 0.7872\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(1, epochs + 1):\n",
    "    loss = train()\n",
    "    auc, ap = test(data.test_pos_edge_index, data.test_neg_edge_index)\n",
    "    print('Epoch: {:03d}, AUC: {:.4f}, AP: {:.4f}'.format(epoch, auc, ap))\n",
    "    \n",
    "    \n",
    "    writer.add_scalar('auc train',auc,epoch) # new line\n",
    "    writer.add_scalar('ap train',ap,epoch)   # new line"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Graph Variational AutoEncoder (GVAE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch_geometric.nn import VGAE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/antonio/anaconda3/envs/geometric_new/lib/python3.9/site-packages/torch_geometric/deprecation.py:12: UserWarning: 'train_test_split_edges' is deprecated, use 'transforms.RandomLinkSplit' instead\n",
      "  warnings.warn(out)\n"
     ]
    }
   ],
   "source": [
    "dataset = Planetoid(\"\\..\", \"CiteSeer\", transform=T.NormalizeFeatures())\n",
    "data = dataset[0]\n",
    "data.train_mask = data.val_mask = data.test_mask = data.y = None\n",
    "data = train_test_split_edges(data)\n",
    "\n",
    "\n",
    "class VariationalGCNEncoder(torch.nn.Module):\n",
    "    def __init__(self, in_channels, out_channels):\n",
    "        super(VariationalGCNEncoder, self).__init__()\n",
    "        self.conv1 = GCNConv(in_channels, 2 * out_channels, cached=True) # cached only for transductive learning\n",
    "        self.conv_mu = GCNConv(2 * out_channels, out_channels, cached=True)\n",
    "        self.conv_logstd = GCNConv(2 * out_channels, out_channels, cached=True)\n",
    "\n",
    "    def forward(self, x, edge_index):\n",
    "        x = self.conv1(x, edge_index).relu()\n",
    "        return self.conv_mu(x, edge_index), self.conv_logstd(x, edge_index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "out_channels = 2\n",
    "num_features = dataset.num_features\n",
    "epochs = 300\n",
    "\n",
    "\n",
    "model = VGAE(VariationalGCNEncoder(num_features, out_channels))  # new line\n",
    "\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "model = model.to(device)\n",
    "x = data.x.to(device)\n",
    "train_pos_edge_index = data.train_pos_edge_index.to(device)\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.01)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train():\n",
    "    model.train()\n",
    "    optimizer.zero_grad()\n",
    "    z = model.encode(x, train_pos_edge_index)\n",
    "    loss = model.recon_loss(z, train_pos_edge_index)\n",
    "    \n",
    "    loss = loss + (1 / data.num_nodes) * model.kl_loss()  # new line\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "    return float(loss)\n",
    "\n",
    "\n",
    "def test(pos_edge_index, neg_edge_index):\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        z = model.encode(x, train_pos_edge_index)\n",
    "    return model.test(z, pos_edge_index, neg_edge_index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 001, AUC: 0.6043, AP: 0.6264\n",
      "Epoch: 002, AUC: 0.4937, AP: 0.5243\n",
      "Epoch: 003, AUC: 0.4943, AP: 0.5001\n",
      "Epoch: 004, AUC: 0.5013, AP: 0.5079\n",
      "Epoch: 005, AUC: 0.5011, AP: 0.5006\n",
      "Epoch: 006, AUC: 0.5022, AP: 0.5011\n",
      "Epoch: 007, AUC: 0.5022, AP: 0.5011\n",
      "Epoch: 008, AUC: 0.5022, AP: 0.5011\n",
      "Epoch: 009, AUC: 0.4978, AP: 0.5007\n",
      "Epoch: 010, AUC: 0.4978, AP: 0.5007\n",
      "Epoch: 011, AUC: 0.4978, AP: 0.5007\n",
      "Epoch: 012, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 013, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 014, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 015, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 016, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 017, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 018, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 019, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 020, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 021, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 022, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 023, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 024, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 025, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 026, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 027, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 028, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 029, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 030, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 031, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 032, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 033, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 034, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 035, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 036, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 037, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 038, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 039, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 040, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 041, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 042, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 043, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 044, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 045, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 046, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 047, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 048, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 049, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 050, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 051, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 052, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 053, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 054, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 055, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 056, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 057, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 058, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 059, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 060, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 061, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 062, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 063, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 064, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 065, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 066, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 067, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 068, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 069, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 070, AUC: 0.5000, AP: 0.5000\n",
      "Epoch: 071, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 072, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 073, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 074, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 075, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 076, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 077, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 078, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 079, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 080, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 081, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 082, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 083, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 084, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 085, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 086, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 087, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 088, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 089, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 090, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 091, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 092, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 093, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 094, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 095, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 096, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 097, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 098, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 099, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 100, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 101, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 102, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 103, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 104, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 105, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 106, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 107, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 108, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 109, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 110, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 111, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 112, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 113, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 114, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 115, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 116, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 117, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 118, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 119, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 120, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 121, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 122, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 123, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 124, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 125, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 126, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 127, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 128, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 129, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 130, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 131, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 132, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 133, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 134, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 135, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 136, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 137, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 138, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 139, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 140, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 141, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 142, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 143, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 144, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 145, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 146, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 147, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 148, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 149, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 150, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 151, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 152, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 153, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 154, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 155, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 156, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 157, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 158, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 159, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 160, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 161, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 162, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 163, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 164, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 165, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 166, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 167, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 168, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 169, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 170, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 171, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 172, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 173, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 174, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 175, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 176, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 177, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 178, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 179, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 180, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 181, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 182, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 183, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 184, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 185, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 186, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 187, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 188, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 189, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 190, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 191, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 192, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 193, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 194, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 195, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 196, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 197, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 198, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 199, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 200, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 201, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 202, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 203, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 204, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 205, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 206, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 207, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 208, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 209, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 210, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 211, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 212, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 213, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 214, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 215, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 216, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 217, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 218, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 219, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 220, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 221, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 222, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 223, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 224, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 225, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 226, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 227, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 228, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 229, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 230, AUC: 0.4989, AP: 0.4995\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 231, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 232, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 233, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 234, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 235, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 236, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 237, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 238, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 239, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 240, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 241, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 242, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 243, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 244, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 245, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 246, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 247, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 248, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 249, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 250, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 251, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 252, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 253, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 254, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 255, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 256, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 257, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 258, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 259, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 260, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 261, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 262, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 263, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 264, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 265, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 266, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 267, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 268, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 269, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 270, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 271, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 272, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 273, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 274, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 275, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 276, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 277, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 278, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 279, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 280, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 281, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 282, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 283, AUC: 0.4989, AP: 0.4995\n",
      "Epoch: 284, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 285, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 286, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 287, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 288, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 289, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 290, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 291, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 292, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 293, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 294, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 295, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 296, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 297, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 298, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 299, AUC: 0.5011, AP: 0.5011\n",
      "Epoch: 300, AUC: 0.5011, AP: 0.5011\n"
     ]
    }
   ],
   "source": [
    "writer = SummaryWriter('runs/VGAE_experiment_'+'2d_100_epochs')\n",
    "\n",
    "for epoch in range(1, epochs + 1):\n",
    "    loss = train()\n",
    "    auc, ap = test(data.test_pos_edge_index, data.test_neg_edge_index)\n",
    "    print('Epoch: {:03d}, AUC: {:.4f}, AP: {:.4f}'.format(epoch, auc, ap))\n",
    "    \n",
    "    \n",
    "    writer.add_scalar('auc train',auc,epoch) # new line\n",
    "    writer.add_scalar('ap train',ap,epoch)   # new line"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
